package ui

import (
	"gioui.org/app"
	"gioui.org/font/gofont"
	"gioui.org/io/key"
	"gioui.org/io/system"
	"gioui.org/layout"
	"gioui.org/op"
	"gioui.org/op/clip"
	"gioui.org/op/paint"
	"gioui.org/text"
	"gioui.org/unit"
	"gioui.org/widget"
	"gioui.org/widget/material"
	"gioui.org/x/markdown"
	"git.sr.ht/~mil/transito/uipages/pageconfig"
	"git.sr.ht/~mil/transito/uipages/pageroute"
	"git.sr.ht/~mil/transito/uipages/pagesearch"
	"git.sr.ht/~mil/transito/uistate"
	"git.sr.ht/~mil/transito/utilfix"
	"github.com/inkeliz/giohyperlink"
	"image"
	"log"
	"os"
)

func CreateUI() {
	utilfix.TimezoneFixAndroid()
	mru := NewUI(app.NewWindow(
		app.Title("Transito"),
		app.Size(unit.Dp(240), unit.Dp(70)),
	))

	go func() {
		if err := mru.Run(mru.UIState.Window); err != nil {
			log.Println(err)
			os.Exit(1)
		}
		os.Exit(0)
	}()
	app.Main()
}

func NewUI(window *app.Window) *UI {
	ui := &UI{
		UIState: uistate.UIState{
			MarkdownRenderer: markdown.NewRenderer(),
			Theme:            material.NewTheme(),
			Sources:          "516",
		},
	}
	ui.UIState.Window = window
	ui.UIState.Theme.Shaper = text.NewShaper(text.WithCollection(gofont.Collection()))
	ui.pageSearch = pagesearch.Initialize(&ui.UIState)
	ui.pageConfig = pageconfig.Initialize(&ui.UIState)
	ui.pageRoute = pageroute.Initialize(&ui.UIState)
	return ui
}

func (ui *UI) Run(w *app.Window) error {
	var ops op.Ops
	for e := range w.Events() {
		giohyperlink.ListenEvents(e)
		switch e := e.(type) {
		case system.FrameEvent:
			gtx := layout.NewContext(&ops, e)
			area := clip.Rect{Max: gtx.Constraints.Max}.Push(gtx.Ops)
			key.InputOp{Tag: w, Keys: key.NameEscape}.Add(gtx.Ops)

			for _, event := range gtx.Events(w) {
				switch event := event.(type) {
				case key.Event:
					if event.Name == key.NameEscape {
						return nil
					}
					if event.Name == key.NameEnter {
						return nil
					}
				}
			}
			ui.Render(gtx)
			area.Pop()
			e.Frame(gtx.Ops)

		case system.DestroyEvent:
			return e.Err
		}
	}

	return nil
}

func (ui *UI) Render(gtx layout.Context) layout.Dimensions {
	var pageOne = ui.pageRoute.Render
	var pageTwo = ui.pageSearch.Render
	var pageThree = ui.pageConfig.Render

	tabButtons := layout.Rigid(func(gtx layout.Context) layout.Dimensions {
		return ui.tabContentList.Layout(gtx, 3, func(gtx layout.Context, tabIdx int) layout.Dimensions {
			var labelString string = ""
			var tabButton *widget.Clickable

			if tabIdx == 0 {
				labelString = "Route"
				tabButton = &ui.tabButton0
			} else if tabIdx == 1 {
				labelString = "Search"
				tabButton = &ui.tabButton1
			} else if tabIdx == 2 {
				labelString = "Config"
				tabButton = &ui.tabButton2
			}

			if tabButton.Clicked() {
				ui.UIState.TabSelected = tabIdx
			}

			var tabWidth int
			return layout.Stack{Alignment: layout.S}.Layout(gtx,
				// Draw tab font
				layout.Stacked(func(gtx layout.Context) layout.Dimensions {
					dims := material.Clickable(gtx, tabButton, func(gtx layout.Context) layout.Dimensions {
						return layout.UniformInset(unit.Dp(12)).Layout(gtx,
							material.H6(ui.UIState.Theme, labelString).Layout,
						)
					})
					tabWidth = dims.Size.X
					return dims
				}),
				// Underline color for active tab
				layout.Stacked(func(gtx layout.Context) layout.Dimensions {
					if ui.UIState.TabSelected != tabIdx {
						return layout.Dimensions{}
					}
					tabHeight := gtx.Dp(unit.Dp(4))
					tabRect := image.Rect(0, 0, tabWidth, tabHeight)
					paint.FillShape(gtx.Ops, ui.UIState.Theme.Palette.ContrastBg, clip.Rect(tabRect).Op())
					return layout.Dimensions{Size: image.Point{X: tabWidth, Y: tabHeight}}
				}),
			)
		})
	})

	// Tab content
	tabContents := layout.Flexed(1, func(gtx layout.Context) layout.Dimensions {
		if ui.UIState.TabSelected == 0 {
			return pageOne(gtx)
		} else if ui.UIState.TabSelected == 1 {
			return pageTwo(gtx)
		} else if ui.UIState.TabSelected == 2 {
			return pageThree(gtx)
		} else {
			return layout.Center.Layout(gtx, material.H1(ui.UIState.Theme, "Unknown").Layout)
		}
	})

	return layout.Flex{Axis: layout.Vertical}.Layout(gtx, tabButtons, tabContents)
}
